package com.qf.commons.core.log;

import org.slf4j.MDC;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

/**
 * description: 监听 SpringBoot的环境参数准备好的事件
 * author: Ken
 * 公众号：Java架构栈
 */
public class LogMDCListener implements GenericApplicationListener {

    private static final String APPLICTION_CONFIG_PROPERTIES = "configurationProperties";

    private static final String APP_NAME = "spring.application.name";

    /**
     * 表示 监听的事件类型，如果返回true，则调用onApplicationEvent方法，进行事件的处理
     * 需要处理 ApplicationEnvironmentPreparedEvent 类型
     * @param eventType 事件类型
     * @return
     */
    @Override
    public boolean supportsEventType(ResolvableType eventType) {
        return ApplicationEnvironmentPreparedEvent.class == eventType.getRawClass();
    }

    /**
     * 处理某个事件
     * @param event - 当前监听到的事件对象
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
//        System.out.println("---->日志环境监听事件触发！");
        //将事件类型强制转换
        ApplicationEnvironmentPreparedEvent environmentPreparedEvent = (ApplicationEnvironmentPreparedEvent) event;
        //获得当前应用的参数环境
        ConfigurableEnvironment environment = environmentPreparedEvent.getEnvironment();
        //获得参数源列表
        MutablePropertySources propertySources = environment.getPropertySources();

//        for (PropertySource<?> propertySource : propertySources) {
//            System.out.println("相关配置源--->" + propertySource.getName());
//        }

        //获取固定名称的参数数据源 - configurationProperties
        PropertySource<?> propertySource = propertySources.get(APPLICTION_CONFIG_PROPERTIES);
        //从该数据源中 获取相关参数
        String appName = (String) propertySource.getProperty(APP_NAME);
//        System.out.println("微服务名称：" + appName);

        //将该微服务的名称 作为日志文件名称放入MDC容器中
        MDC.put("logName", appName);
        MDC.put("logPath", appName);
    }

    /**
     * 设置监听器的优先级
     * @return
     */
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 19;
    }
}
